﻿using Furion.FriendlyException;

namespace Api;

/// <summary>
/// 小程序接口
/// </summary>
public class WechatAppletApi : Furion.DependencyInjection.ITransient
{
    private readonly ISqlSugarClient db;

    private string AppId { get { return App.Configuration.GetSection("applet:wechat:id").Value ?? ""; } }

    private string AppSecret { get { return App.Configuration.GetSection("applet:wechat:secret").Value ?? ""; } }

    /// <summary>
    /// 小程序接口
    /// </summary>
    /// <param name="db"></param>
    public WechatAppletApi(ISqlSugarClient db)
    {
        this.db = db;
    }

    /// <summary>
    /// 登录
    /// </summary>
    /// <param name="code"></param>
    /// <returns></returns>
    public async Task<(string, string, string)> Login(string code)
    {
        string url = $"https://api.weixin.qq.com/sns/jscode2session?appid={AppId}&secret={AppSecret}&js_code={code}&grant_type=authorization_code";

        var result = await Http.Get<dynamic>(url);

        if (result.openid != null)
        {
            return (result.openid, result.session_key, "");
        }

        throw Oops.Oh(result.errmsg);
    }


    /// <summary>
    /// 获取token
    /// </summary>
    /// <returns></returns>
    public async Task<string> GetToken()
    {
        string key = "wechat_applet_token";

        if (await RedisHelper.ExistsAsync(key))
        {
            return await RedisHelper.GetAsync(key);
        }

        string url = $"https://api.weixin.qq.com/cgi-bin/token?appid={AppId}&secret={AppSecret}&grant_type=client_credential";

        var result = await Http.Get<dynamic>(url);

        if (result.access_token != null)
        {
            string token = result.access_token;

            int expires = result.expires_in;

            await RedisHelper.SetAsync(key, token, expires);

            return token;
        }

        throw Oops.Oh(result.errmsg);
    }


    /// <summary>
    /// 获取二维码
    /// </summary>
    /// <param name="scene"></param>
    /// <param name="page"></param>
    /// <param name="env_version"></param>
    /// <returns></returns>
    public async Task<object> CreatedQrCode(string scene, string page, string env_version)
    {
        string url = $"https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token={await GetToken()}";

        var data = new
        {
            scene,
            page,
            env_version,
            check_path = false
        };

        var result = await Http.Post(url, data);

        return result;
    }

    /// <summary>
    /// 微信发货
    /// </summary>
    /// <param name="orderNo"></param>
    /// <param name="goodsInfo"></param>
    /// <param name="openId"></param>
    /// <param name="logistics_type">2同城 3虚拟</param>
    /// <returns></returns>
    public async Task<bool> SendOrder(string orderNo, string goodsInfo, string openId, int logistics_type)
    {
        Console.WriteLine($"微信发货:{orderNo};{goodsInfo};{openId};{logistics_type}");

        string mchId = App.Configuration.GetSection("WeChatPay:MchId").Value ?? "";

        string url = $"https://api.weixin.qq.com/wxa/sec/order/upload_shipping_info?access_token={await GetToken()}";

        var data = new
        {
            order_key = new
            {
                order_number_type = 1,

                out_trade_no = orderNo,

                mchid = mchId
            },

            logistics_type = logistics_type,

            delivery_mode = "UNIFIED_DELIVERY",

            shipping_list = new List<dynamic>
            {
               new
               {
                   item_desc = goodsInfo
               }
            },

            upload_time = DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss.120+08:00"),

            payer = new
            {
                openid = openId
            },

        };

        var result = await Http.Post<dynamic>(url, data);

        if (result.errcode != 0) throw Oops.Oh(result.errmsg);

        return true;
    }


}
